wayland: add shortcut inhibitor support
authorOlivier Fourdan <ofourdan@redhat.com>
Wed, 22 Mar 2017 09:21:02 +0000 (10:21 +0100)
committerOlivier Fourdan <ofourdan@redhat.com>
Wed, 2 Aug 2017 10:37:23 +0000 (12:37 +0200)
This adds support for the shortcut inhibitor protocol in gdk/wayland
backend.

A shortcut inhibitor request is issued from the gdk wayland backend for
both the older, deprecated API gdk_device_grab() and the new gdk seat
API gdk_seat_grab(), but only if the requested capability is for the
keyboard only.

https://bugzilla.gnome.org/show_bug.cgi?id=783343

configure.ac
gdk/wayland/Makefile.am
gdk/wayland/gdkdevice-wayland.c
gdk/wayland/gdkdisplay-wayland.c
gdk/wayland/gdkdisplay-wayland.h
gdk/wayland/gdkprivate-wayland.h
gdk/wayland/gdkwindow-wayland.c

index 49c59d7ed0d505a9ca003b0672dbd945ebd1a0a8..301310219efeb4732418f01bd8cb12ce3fc93fd1 100644 (file)
@@ -60,7 +60,7 @@ m4_define([cairo_required_version], [1.14.0])
 m4_define([gdk_pixbuf_required_version], [2.30.0])
 m4_define([introspection_required_version], [1.39.0])
 m4_define([wayland_required_version], [1.9.91])
-m4_define([wayland_protocols_required_version], [1.7])
+m4_define([wayland_protocols_required_version], [1.9])
 m4_define([mirclient_required_version], [0.22.0])
 m4_define([mircookie_required_version], [0.17.0])
 m4_define([epoxy_required_version], [1.0])
index d4983cf2a5f15903081e5e60ed4ffc32fc5d11ff..408bf7be5cdb2c5ee4ef8fa412a156c7ae1f976c 100644 (file)
@@ -31,6 +31,8 @@ BUILT_SOURCES =                               \
        gtk-primary-selection-protocol.c                        \
        tablet-unstable-v2-client-protocol.h    \
        tablet-unstable-v2-protocol.c           \
+       keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h \
+       keyboard-shortcuts-inhibit-unstable-v1-protocol.c       \
        gtk-shell-client-protocol.h             \
        gtk-shell-protocol.c
 
index 011fe30e2dfe1acd50d85bd33150ca3010e4944f..e1bccc606d73481802a5c1c97a728e3b7786d0df 100644 (file)
@@ -757,6 +757,8 @@ gdk_wayland_device_grab (GdkDevice    *device,
   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
     {
       /* Device is a keyboard */
+      gdk_wayland_window_inhibit_shortcuts (window,
+                                            gdk_device_get_seat (device));
       return GDK_GRAB_SUCCESS;
     }
   else
@@ -813,6 +815,9 @@ gdk_wayland_device_ungrab (GdkDevice *device,
   if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
     {
       /* Device is a keyboard */
+      if (prev_focus)
+        gdk_wayland_window_restore_shortcuts (prev_focus,
+                                              gdk_device_get_seat (device));
     }
   else
     {
@@ -4756,6 +4761,10 @@ gdk_wayland_seat_grab (GdkSeat                *seat,
                                     _gdk_display_get_next_serial (display),
                                     evtime,
                                     FALSE);
+
+      /* Inhibit shortcuts if the seat grab is for the keyboard only */
+      if (capabilities == GDK_SEAT_CAPABILITY_KEYBOARD)
+        gdk_wayland_window_inhibit_shortcuts (window, seat);
     }
 
   if (wayland_seat->tablets &&
@@ -4827,7 +4836,11 @@ gdk_wayland_seat_ungrab (GdkSeat *seat)
       grab = _gdk_display_get_last_device_grab (display, wayland_seat->master_keyboard);
 
       if (grab)
-        grab->serial_end = grab->serial_start;
+        {
+          grab->serial_end = grab->serial_start;
+          if (grab->window)
+            gdk_wayland_window_restore_shortcuts (grab->window, seat);
+        }
     }
 
   if (wayland_seat->touch_master)
index 0baa2de21c6322f74b429e8ef9c37aabd19c8107..8f8c1ddc9aab90447ad85844796067c2aaefca04 100644 (file)
@@ -451,6 +451,12 @@ gdk_registry_handle_global (void               *data,
         wl_registry_bind (display_wayland->wl_registry, id,
                           &zxdg_importer_v1_interface, 1);
     }
+  else if (strcmp (interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0)
+    {
+      display_wayland->keyboard_shortcuts_inhibit =
+        wl_registry_bind (display_wayland->wl_registry, id,
+                          &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
+    }
   else
     handled = FALSE;
 
index 1270405e11fef642e854c69520a50c277845c4b4..3f53108a158c90012239b109c014d5f45bae2bdc 100644 (file)
@@ -31,6 +31,7 @@
 #include <gdk/wayland/gtk-shell-client-protocol.h>
 #include <gdk/wayland/xdg-shell-unstable-v6-client-protocol.h>
 #include <gdk/wayland/xdg-foreign-unstable-v1-client-protocol.h>
+#include <gdk/wayland/keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h>
 
 #include <glib.h>
 #include <gdk/gdkkeys.h>
@@ -77,6 +78,7 @@ struct _GdkWaylandDisplay
   struct zwp_tablet_manager_v2 *tablet_manager;
   struct zxdg_exporter_v1 *xdg_exporter;
   struct zxdg_importer_v1 *xdg_importer;
+  struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit;
 
   GList *async_roundtrips;
 
index 96c15367106ed88830821e08e4d9fab55e467101..09590b81b3c571e72273ddd224ecd33261567b2e 100644 (file)
@@ -281,4 +281,9 @@ void gdk_wayland_seat_set_global_cursor (GdkSeat   *seat,
 
 struct wl_output *gdk_wayland_window_get_wl_output (GdkWindow *window);
 
+void gdk_wayland_window_inhibit_shortcuts (GdkWindow *window,
+                                           GdkSeat   *gdk_seat);
+void gdk_wayland_window_restore_shortcuts (GdkWindow *window,
+                                           GdkSeat   *gdk_seat);
+
 #endif /* __GDK_PRIVATE_WAYLAND_H__ */
index dbaf7e08a1197a00732bd584385e774ca6871ad3..1b42371a466acc53e327f52d967c9741b4d10274 100644 (file)
@@ -204,6 +204,7 @@ struct _GdkWindowImplWayland
   } exported;
 
   struct zxdg_imported_v1 *imported_transient_for;
+  GHashTable *shortcuts_inhibitors;
 };
 
 struct _GdkWindowImplWaylandClass
@@ -668,6 +669,7 @@ _gdk_wayland_display_create_window_impl (GdkDisplay    *display,
   impl = g_object_new (GDK_TYPE_WINDOW_IMPL_WAYLAND, NULL);
   window->impl = GDK_WINDOW_IMPL (impl);
   impl->wrapper = GDK_WINDOW (window);
+  impl->shortcuts_inhibitors = g_hash_table_new (NULL, NULL);
 
   if (window->width > 65535)
     {
@@ -968,6 +970,8 @@ gdk_window_impl_wayland_finalize (GObject *object)
   g_clear_pointer (&impl->input_region, cairo_region_destroy);
   g_clear_pointer (&impl->staged_updates_region, cairo_region_destroy);
 
+  g_hash_table_destroy (impl->shortcuts_inhibitors);
+
   G_OBJECT_CLASS (_gdk_window_impl_wayland_parent_class)->finalize (object);
 }
 
@@ -4163,3 +4167,50 @@ gdk_wayland_window_set_transient_for_exported (GdkWindow *window,
 
   return TRUE;
 }
+
+static struct zwp_keyboard_shortcuts_inhibitor_v1 *
+gdk_wayland_window_get_inhibitor (GdkWindowImplWayland *impl,
+                                  struct wl_seat *seat)
+{
+  return g_hash_table_lookup (impl->shortcuts_inhibitors, seat);
+}
+
+void
+gdk_wayland_window_inhibit_shortcuts (GdkWindow *window,
+                                      GdkSeat   *gdk_seat)
+{
+  GdkWindowImplWayland *impl= GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
+  struct wl_surface *surface = impl->display_server.wl_surface;
+  struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
+  struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
+
+  if (display->keyboard_shortcuts_inhibit == NULL)
+    return;
+
+  if (gdk_wayland_window_get_inhibitor (impl, seat))
+    return; /* Already inhibitted */
+
+  inhibitor =
+      zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts (
+          display->keyboard_shortcuts_inhibit, surface, seat);
+
+  g_hash_table_insert (impl->shortcuts_inhibitors, seat, inhibitor);
+}
+
+void
+gdk_wayland_window_restore_shortcuts (GdkWindow *window,
+                                      GdkSeat   *gdk_seat)
+{
+  GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+  struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
+  struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
+
+  inhibitor = gdk_wayland_window_get_inhibitor (impl, seat);
+  if (inhibitor == NULL)
+    return; /* Not inhibitted */
+
+  zwp_keyboard_shortcuts_inhibitor_v1_destroy (inhibitor);
+  g_hash_table_remove (impl->shortcuts_inhibitors, seat);
+}
+